package cn.serein.charging.order.rabbit;


import cn.serein.charging.order.config.RabbitMQConfiguration;
import cn.serein.charging.order.pojo.po.OrderMQPO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class RabbitMQOrderProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendOrder(OrderMQPO orderMQPO){

        // 设置RabbitMQ的回调
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setReturnsCallback(returnedMessage -> {

            //returnedMessage 包含被退掉的信息,消息本身,错误码,错误的消息,
            //退订发生哪个交换机 ,发生在哪个路由key
            log.debug("returnedMessage:{}",returnedMessage);
        });

        // 设置RabbitMQ的确认机制
        //
        //消息队列中的ack
        //consumeChargingQueue 消费者 从Rabbitmq 消费消息 ,处理业务 更新订单状态
        //  正常情况  自动ack 默认
        //      更新订单状态,返回ack给消息队列
        //      消息队列收到消费者发送的ack后,任务消费者消费消息成功了,消息队列会把这条消息从队列中删除,消费者可以继续消费下一条消息
        //  异常情况
        //      更新订单状态,数据库出现异常,更新失败,消费者会抛异常,如果是自动ack,还是返回ack给消息队列,消息队列收到ack 删除消息
        //   改为手动ack,如果更新失败,不返回ack给消息队列
        //      消息队列没有收到ack,认为消费者没有成功消费消息,不会删除,会一直保存
        //   等数据库恢复,消费者会继续重新消费这条消息,继续更新订单的状态,消息没丢.
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            log.debug("correlationData:{},ack:{},cause:{}",correlationData,ack,cause);
            if(!ack){
                log.debug("发送消息失败");
            }else{
                log.debug("发送消息成功");
            }

        });


        rabbitTemplate.convertAndSend(RabbitMQConfiguration.EXCHANGE_NAME,
                RabbitMQConfiguration.ROUTING_KEY,orderMQPO);


    }


}
